import traceback
from queue import Empty, Queue
from threading import Thread
import facade


class ThreadVal(object):
    """
    该对象维护线程函数的变量以及与线程对象间的交互
    """

    def __init__(self):
        # 该线程是否愿意被删除
        self.thread_delete = False
        # 线程初始化参数
        self.args = ()
        self.kwargs = None
        self.queue = Queue(1)

    def set_args(self, args):
        self.args = args

    def set_kwargs(self, kwargs):
        self.kwargs = kwargs


class ThreadManager(Thread):
    """
    定义线程类，继承threading.Thread
    该类主要实现线程的运行
    """

    def __init__(self, work_queue, result_queue, thread_queue, logger=None, group=None, target=None, name=None,
                 args=(), kwargs=None, daemon=True):
        super(ThreadManager, self).__init__(group, target, name,
                                            args, kwargs, daemon=daemon)
        if logger:
            self.logger = logger
        else:
            self.logger = facade.get_streamlogger()
        # self.kwargs = kwargs
        # self.args = args
        # 接受两个队列 一个处理结果 一个发送任务
        self.work_queue = work_queue
        self.result_queue = result_queue
        # 线程队列
        self.thread_queue = thread_queue
        # 主线程退出  该线程也会退出
        self.daemon = True
        # 一个标识 如果为False代表线程运行完毕等待新的任务到来,否则表示任务正在运行
        # 这个标志是为了检查程序在运行中还是等待状态
        self.runstatus = False
        # 设置该标志是为了表示是否愿意被重新启动，因为有些线程只需要运行一次
        # 而有的需要长期运行且有一定的重启机制
        self.is_restart = True
        # 为了兼容普通线程类模式  "default" 自己写的run 方法  "super": 父类的run方法
        self.mode = "default"
        # 是否愿意被删除 有时候我们需要删除一批线程 但是 线程不能中间
        # 状态被删除 故需要设置该标志 在 self.threadval 中也会维护一个
        # 两个状态该标准表示该线程能否被删，self.threadval维护的是该线程是否被删除
        # 一个是使能，一个是删除信号
        self.thread_delete = True
        # 线程内部的一个类对象 每个线程维护一个保证里面的数据线程安全，以后为每个线程提供服务
        self.threadval = ThreadVal()
        self.threadval.result_queue = result_queue
        self.threadval.thread_queue = thread_queue
        self.set_args(self._args)
        self.set_kwargs(self._kwargs)

    def set_args(self, args):
        self._args = args
        self.threadval.set_args(args)

    def set_kwargs(self, kwargs):
        self._kwargs = kwargs
        self.threadval.set_kwargs(self._kwargs)

    def get_runstatus(self):
        return self.runstatus

    def set_runstatus(self, runstatus):
        self.runstatus = runstatus

    def get_is_restart(self):
        return self.is_restart

    def set_is_restart(self, is_restart):
        self.is_restart = is_restart

    def set_mode(self, mode):
        self.mode = mode

    def get_mode(self):
        return self.mode

    def run(self):
        if self.mode == "default":
            self.run1()
        elif self.mode == "super":
            try:
                super().run()
            except:
                self.logger.info(traceback.format_exc())
        else:
            raise Exception("运行模式错误 请检查 default or super")

    def run1(self):
        """
        启动线程
        :return:
        """
        while True:
            try:
                if self.thread_delete and self.threadval.thread_delete:
                    self.logger.info("主动停止线程{},因为两个信号量都为True".format(self.getName()))
                    break
                self.runstatus = False
                try:
                    target, args, kwargs = self.work_queue.get(timeout=30)
                    self.runstatus = True  # 代表取到工作队列的值
                    target(self.threadval, *args, **kwargs)
                    self.work_queue.task_done()
                except Empty:
                    pass
            except SystemExit as e:
                self.runstatus = False
                if e.args == (-1,):
                    self.logger.error("由逻辑判断主动退出当前线程")
                    break
                else:
                    self.logger.error("其他SystemExit错误，检查逻辑")
            except:
                self.runstatus = False
                self.logger.error(traceback.format_exc())
